//
// Created by edward on 22-11-16.
// use condtion_variable to genenrate a thread safe message queue
//

#include "utils.h"
#include <mutex>
#include <queue>
#include <condition_variable>
#include <iostream>
#include <thread>
#include <string>


template<typename T>
class MessageQueue {
public:
    void push(T t) {
        std::lock_guard lk(mtx_);       //互斥保护数据
        queue_.push(std::move(t));
        cond_.notify_one();                //临界区内发送通知，避免优先级反转和条件变量失效
    }
    T pop() {
        T frnt;
        std::unique_lock lk(mtx_);
        cond_.wait(lk, [&](){
            return !queue_.empty();
        });
        frnt = std::move(queue_.front());
        queue_.pop();
        return frnt;
    }
private:
    mutable std::mutex mtx_;
    mutable std::condition_variable cond_;
    std::queue<T> queue_;
};

using namespace std;

template<typename T>
void data_prepare(MessageQueue<T> &messageQueue) {
    T t;
    while (cin >> t) {
        messageQueue.push(std::move(t));
    }
}

template<typename T>
void data_process(MessageQueue<T> &messageQueue) {
    T t;
    int idx = 0;
    while (true) {
        t = messageQueue.pop(); //数据的处理在临界区外
        edward::print("[", idx++, "]:", t);
    }
}

int main() {
    MessageQueue<string> messageQueue;
    edward::print("test begin:");
    thread preparer(data_prepare<string>, ref(messageQueue));
    thread processer(data_process<string>, ref(messageQueue));
    preparer.join();
    //不用等待processer，如果preparer结束，则直接推出进程
    return 0;
}